package com.bear.atlassianmcp.oauth.util;

import com.bear.atlassianmcp.oauth.model.OAuthToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * OAuth 令牌解析工具
 * 用于解析请求头中的 OAuth 令牌信息
 */
@Component
public class OAuthTokenParser {
    
    private static final Logger logger = LoggerFactory.getLogger(OAuthTokenParser.class);
    
    /**
     * 从 Authorization 头中解析 OAuth 令牌
     * 
     * 支持的格式：
     * OAuth oauth_token=xxx&oauth_token_secret=yyy&service_type=jira
     * OAuth oauth_token=xxx,oauth_token_secret=yyy,service_type=jira
     * 
     * @param authorizationHeader Authorization 头内容
     * @return 解析后的 OAuth 令牌，如果解析失败返回 null
     */
    public OAuthToken parseFromAuthorizationHeader(String authorizationHeader) {
        if (authorizationHeader == null || !authorizationHeader.startsWith("OAuth ")) {
            logger.debug("Invalid OAuth authorization header format");
            return null;
        }
        
        try {
            // 移除 "OAuth " 前缀
            String tokenData = authorizationHeader.substring(6).trim();
            
            // 解析参数
            Map<String, String> params = parseTokenParameters(tokenData);
            
            // 提取必需的参数
            String oauthToken = params.get("oauth_token");
            String oauthTokenSecret = params.get("oauth_token_secret");
            String serviceTypeStr = params.get("service_type");
            
            if (oauthToken == null || oauthTokenSecret == null) {
                logger.warn("Missing required OAuth parameters: oauth_token or oauth_token_secret");
                return null;
            }
            
            // 确定服务类型
            OAuthToken.ServiceType serviceType = parseServiceType(serviceTypeStr);
            if (serviceType == null) {
                logger.warn("Invalid or missing service_type parameter: {}", serviceTypeStr);
                return null;
            }
            
            // 创建 OAuth Token
            OAuthToken token = new OAuthToken(oauthToken, oauthTokenSecret, 
                                            OAuthToken.TokenType.ACCESS_TOKEN, serviceType);
            token.setAuthorized(true);
            
            // 设置可选参数
            if (params.containsKey("user_id")) {
                token.setUserId(params.get("user_id"));
            }
            
            logger.debug("Successfully parsed OAuth token for service: {}", serviceType);
            return token;
            
        } catch (Exception e) {
            logger.error("Failed to parse OAuth token from authorization header: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 解析令牌参数
     * 支持 & 和 , 两种分隔符
     */
    private Map<String, String> parseTokenParameters(String tokenData) {
        Map<String, String> params = new HashMap<>();
        
        // 尝试使用 & 分隔符
        if (tokenData.contains("&")) {
            String[] pairs = tokenData.split("&");
            for (String pair : pairs) {
                parseKeyValuePair(pair, params);
            }
        } 
        // 尝试使用 , 分隔符
        else if (tokenData.contains(",")) {
            String[] pairs = tokenData.split(",");
            for (String pair : pairs) {
                parseKeyValuePair(pair, params);
            }
        }
        // 单个参数对
        else {
            parseKeyValuePair(tokenData, params);
        }
        
        return params;
    }
    
    /**
     * 解析单个键值对
     */
    private void parseKeyValuePair(String pair, Map<String, String> params) {
        try {
            String[] keyValue = pair.trim().split("=", 2);
            if (keyValue.length == 2) {
                String key = URLDecoder.decode(keyValue[0].trim(), StandardCharsets.UTF_8);
                String value = URLDecoder.decode(keyValue[1].trim(), StandardCharsets.UTF_8);
                params.put(key, value);
            }
        } catch (Exception e) {
            logger.debug("Failed to parse key-value pair: {}", pair);
        }
    }
    
    /**
     * 解析服务类型
     */
    private OAuthToken.ServiceType parseServiceType(String serviceTypeStr) {
        if (serviceTypeStr == null) {
            return null;
        }
        
        String lowerServiceType = serviceTypeStr.toLowerCase().trim();
        switch (lowerServiceType) {
            case "jira":
                return OAuthToken.ServiceType.JIRA;
            case "confluence":
                return OAuthToken.ServiceType.CONFLUENCE;
            default:
                return null;
        }
    }
    
    /**
     * 将 OAuth 令牌格式化为 Authorization 头格式
     * 
     * @param token OAuth 令牌
     * @return 格式化后的 Authorization 头内容
     */
    public String formatToAuthorizationHeader(OAuthToken token) {
        if (token == null || !token.isValidAccessToken()) {
            return null;
        }
        
        try {
            StringBuilder sb = new StringBuilder("OAuth ");
            
            // 必需参数
            sb.append("oauth_token=").append(urlEncode(token.getToken()));
            sb.append("&oauth_token_secret=").append(urlEncode(token.getTokenSecret()));
            sb.append("&service_type=").append(urlEncode(token.getServiceType().name().toLowerCase()));
            
            // 可选参数
            if (token.getUserId() != null) {
                sb.append("&user_id=").append(urlEncode(token.getUserId()));
            }
            
            return sb.toString();
            
        } catch (Exception e) {
            logger.error("Failed to format OAuth token to authorization header: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * URL 编码
     */
    private String urlEncode(String value) {
        if (value == null) {
            return "";
        }
        return java.net.URLEncoder.encode(value, StandardCharsets.UTF_8);
    }
    
    /**
     * 验证 OAuth 令牌格式
     * 
     * @param authorizationHeader Authorization 头内容
     * @return 如果格式有效返回 true
     */
    public boolean isValidOAuthFormat(String authorizationHeader) {
        if (authorizationHeader == null || !authorizationHeader.startsWith("OAuth ")) {
            return false;
        }
        
        try {
            String tokenData = authorizationHeader.substring(6).trim();
            Map<String, String> params = parseTokenParameters(tokenData);
            
            // 检查必需参数
            return params.containsKey("oauth_token") && 
                   params.containsKey("oauth_token_secret") &&
                   params.containsKey("service_type");
                   
        } catch (Exception e) {
            return false;
        }
    }
    
    /**
     * 从 OAuth 令牌中提取服务类型
     * 
     * @param authorizationHeader Authorization 头内容
     * @return 服务类型，如果无法解析返回 null
     */
    public OAuthToken.ServiceType extractServiceType(String authorizationHeader) {
        if (!isValidOAuthFormat(authorizationHeader)) {
            return null;
        }
        
        try {
            String tokenData = authorizationHeader.substring(6).trim();
            Map<String, String> params = parseTokenParameters(tokenData);
            return parseServiceType(params.get("service_type"));
        } catch (Exception e) {
            logger.debug("Failed to extract service type from OAuth header: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 创建示例 OAuth 令牌格式说明
     * 
     * @return 示例格式字符串
     */
    public String getExampleFormat() {
        return "OAuth oauth_token=your_access_token&oauth_token_secret=your_token_secret&service_type=jira";
    }
    
    /**
     * 验证并解析 OAuth 令牌，提供详细的错误信息
     * 
     * @param authorizationHeader Authorization 头内容
     * @return 解析结果，包含令牌或错误信息
     */
    public ParseResult parseWithValidation(String authorizationHeader) {
        ParseResult result = new ParseResult();
        
        if (authorizationHeader == null) {
            result.error = "Authorization header is null";
            return result;
        }
        
        if (!authorizationHeader.startsWith("OAuth ")) {
            result.error = "Authorization header must start with 'OAuth '";
            return result;
        }
        
        try {
            String tokenData = authorizationHeader.substring(6).trim();
            if (tokenData.isEmpty()) {
                result.error = "OAuth token data is empty";
                return result;
            }
            
            Map<String, String> params = parseTokenParameters(tokenData);
            
            // 验证必需参数
            if (!params.containsKey("oauth_token")) {
                result.error = "Missing required parameter: oauth_token";
                return result;
            }
            
            if (!params.containsKey("oauth_token_secret")) {
                result.error = "Missing required parameter: oauth_token_secret";
                return result;
            }
            
            if (!params.containsKey("service_type")) {
                result.error = "Missing required parameter: service_type";
                return result;
            }
            
            OAuthToken.ServiceType serviceType = parseServiceType(params.get("service_type"));
            if (serviceType == null) {
                result.error = "Invalid service_type. Must be 'jira' or 'confluence'";
                return result;
            }
            
            // 创建令牌
            result.token = parseFromAuthorizationHeader(authorizationHeader);
            result.success = true;
            
            return result;
            
        } catch (Exception e) {
            result.error = "Failed to parse OAuth token: " + e.getMessage();
            return result;
        }
    }
    
    /**
     * 解析结果类
     */
    public static class ParseResult {
        public boolean success = false;
        public OAuthToken token = null;
        public String error = null;
        
        public boolean isSuccess() {
            return success;
        }
        
        public OAuthToken getToken() {
            return token;
        }
        
        public String getError() {
            return error;
        }
    }
}
